home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n03 / dflt10.exe / EDITBOX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  35.5 KB  |  1,138 lines

  1. /* ------------- editbox.c ------------ */
  2. #include "dflat.h"
  3.  
  4. #define EditBufLen(wnd) (isMultiLine(wnd) ? EDITLEN : ENTRYLEN)
  5. #define SetLinePointer(wnd, ln) (wnd->CurrLine = ln)
  6. #define isWhite(c)     ((c)==' '||(c)=='\n')
  7. /* ---------- local prototypes ----------- */
  8. static void SaveDeletedText(WINDOW, char *, int);
  9. static void Forward(WINDOW);
  10. static void Backward(WINDOW);
  11. static void End(WINDOW);
  12. static void Home(WINDOW);
  13. static void Downward(WINDOW);
  14. static void Upward(WINDOW);
  15. static void StickEnd(WINDOW);
  16. static void NextWord(WINDOW);
  17. static void PrevWord(WINDOW);
  18. static void ModTextPointers(WINDOW, int, int);
  19. /* -------- local variables -------- */
  20. static int KeyBoardMarking, ButtonDown;
  21. static int TextMarking;
  22. static int ButtonX, ButtonY;
  23. static int PrevY = -1;
  24.  
  25. /* ----------- CREATE_WINDOW Message ---------- */
  26. static int CreateWindowMsg(WINDOW wnd)
  27. {
  28.     int rtn = BaseWndProc(EDITBOX, wnd, CREATE_WINDOW, 0, 0);
  29.     wnd->MaxTextLength = MAXTEXTLEN+1;
  30.     wnd->textlen = EditBufLen(wnd);
  31.     wnd->InsertMode = TRUE;
  32.     ResetEditBox(wnd);
  33.     return rtn;
  34. }
  35. /* ----------- SETTEXT Message ---------- */
  36. static int SetTextMsg(WINDOW wnd, PARAM p1)
  37. {
  38.     int rtn = FALSE;
  39.     if (strlen((char *)p1) <= wnd->MaxTextLength)    {
  40.         rtn = BaseWndProc(EDITBOX, wnd, SETTEXT, p1, 0);
  41.         wnd->CurrLine = 0;
  42.     }
  43.     return rtn;
  44. }
  45. /* ----------- ADDTEXT Message ---------- */
  46. static int AddTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  47. {
  48.     int rtn = FALSE;
  49.     if (strlen((char *)p1)+wnd->textlen <= wnd->MaxTextLength) {
  50.         rtn = BaseWndProc(EDITBOX, wnd, ADDTEXT, p1, p2);
  51.         if (rtn != FALSE)    {
  52.             if (!isMultiLine(wnd))    {
  53.                 wnd->CurrLine = 0;
  54.                 wnd->CurrCol = strlen((char *)p1);
  55.                 if (wnd->CurrCol >= ClientWidth(wnd))    {
  56.                     wnd->wleft = wnd->CurrCol-ClientWidth(wnd);
  57.                     wnd->CurrCol -= wnd->wleft;
  58.                 }
  59.                 wnd->BlkEndCol = wnd->CurrCol;
  60.                 SendMessage(wnd, KEYBOARD_CURSOR,
  61.                                      WndCol, wnd->WndRow);
  62.             }
  63.         }
  64.     }
  65.     return rtn;
  66. }
  67. /* ----------- GETTEXT Message ---------- */
  68. static int GetTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  69. {
  70.     char *cp1 = (char *)p1;
  71.     char *cp2 = wnd->text;
  72.     if (cp2 != NULL)    {
  73.         while (p2-- && *cp2 && *cp2 != '\n')
  74.             *cp1++ = *cp2++;
  75.         *cp1 = '\0';
  76.         return TRUE;
  77.     }
  78.     return FALSE;
  79. }
  80. /* ----------- SETTEXTLENGTH Message ---------- */
  81. static int SetTextLengthMsg(WINDOW wnd, unsigned int len)
  82. {
  83.     if (++len < MAXTEXTLEN)    {
  84.         wnd->MaxTextLength = len;
  85.         if (len < wnd->textlen)    {
  86.             if ((wnd->text=realloc(wnd->text, len+2)) != NULL) {
  87.                 wnd->textlen = len;
  88.                 *((wnd->text)+len) = '\0';
  89.                 *((wnd->text)+len+1) = '\0';
  90.                 BuildTextPointers(wnd);
  91.             }
  92.         }
  93.         return TRUE;
  94.     }
  95.     return FALSE;
  96. }
  97. /* ----------- KEYBOARD_CURSOR Message ---------- */
  98. static int KeyboardCursorMsg(WINDOW wnd, PARAM p1, PARAM p2)
  99. {
  100.     int rtn;
  101.     wnd->CurrCol = (int)p1 + wnd->wleft;
  102.     wnd->WndRow = (int)p2;
  103.     wnd->CurrLine = (int)p2 + wnd->wtop;
  104.     rtn = BaseWndProc(EDITBOX, wnd, KEYBOARD_CURSOR, p1, p2);
  105.     if (wnd == inFocus && CharInView(wnd, (int)p1, (int)p2))
  106.         SendMessage(NULL, SHOW_CURSOR, wnd->InsertMode, 0);
  107.     else SendMessage(NULL, HIDE_CURSOR, 0, 0);
  108.     return rtn;
  109. }
  110. /* ----------- SIZE Message ---------- */
  111. int SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
  112. {
  113.     int rtn = BaseWndProc(EDITBOX, wnd, SIZE, p1, p2);
  114.     if (WndCol > ClientWidth(wnd)-1)
  115.         wnd->CurrCol = ClientWidth(wnd)-1 + wnd->wleft;
  116.     if (wnd->WndRow > ClientHeight(wnd)-1)    {
  117.         wnd->WndRow = ClientHeight(wnd)-1;
  118.         SetLinePointer(wnd, wnd->WndRow+wnd->wtop);
  119.     }
  120.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  121.     return rtn;
  122. }
  123. /* ----------- SCROLL Message ---------- */
  124. static int ScrollMsg(WINDOW wnd, PARAM p1)
  125. {
  126.     int rtn = FALSE;
  127.     if (isMultiLine(wnd))    {
  128.         rtn = BaseWndProc(EDITBOX,wnd,SCROLL,p1,0);
  129.         if (rtn != FALSE)    {
  130.             if (p1)    {
  131.                 /* -------- scrolling up --------- */
  132.                 if (wnd->WndRow == 0)    {
  133.                     wnd->CurrLine++;
  134.                     StickEnd(wnd);
  135.                 }
  136.                 else
  137.                     --wnd->WndRow;
  138.             }
  139.             else    {
  140.                 /* -------- scrolling down --------- */
  141.                 if (wnd->WndRow == ClientHeight(wnd)-1)    {
  142.                     if (wnd->CurrLine > 0)
  143.                         --wnd->CurrLine;
  144.                     StickEnd(wnd);
  145.                 }
  146.                 else
  147.                     wnd->WndRow++;
  148.             }
  149.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  150.         }
  151.     }
  152.     return rtn;
  153. }
  154. /* ----------- HORIZSCROLL Message ---------- */
  155. static int HorizScrollMsg(WINDOW wnd, PARAM p1)
  156. {
  157.     int rtn = FALSE;
  158.     char *currchar = CurrChar;
  159.     if (!(p1 &&
  160.             wnd->CurrCol == wnd->wleft && *currchar == '\n'))  {
  161.         rtn = BaseWndProc(EDITBOX, wnd, HORIZSCROLL, p1, 0);
  162.         if (rtn != FALSE)    {
  163.             if (wnd->CurrCol < wnd->wleft)
  164.                 wnd->CurrCol++;
  165.             else if (WndCol == ClientWidth(wnd))
  166.                 --wnd->CurrCol;
  167.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  168.         }
  169.     }
  170.     return rtn;
  171. }
  172. /* ----------- SCROLLPAGE Message ---------- */
  173. static int ScrollPageMsg(WINDOW wnd, PARAM p1)
  174. {
  175.     int rtn = FALSE;
  176.     if (isMultiLine(wnd))    {
  177.         rtn = BaseWndProc(EDITBOX, wnd, SCROLLPAGE, p1, 0);
  178.         SetLinePointer(wnd, wnd->wtop+wnd->WndRow);
  179.         StickEnd(wnd);
  180.         SendMessage(wnd, KEYBOARD_CURSOR,WndCol, wnd->WndRow);
  181.     }
  182.     return rtn;
  183. }
  184. /* ----------- HORIZSCROLLPAGE Message ---------- */
  185. static int HorizPageMsg(WINDOW wnd, PARAM p1)
  186. {
  187.     int rtn = BaseWndProc(EDITBOX, wnd, HORIZPAGE, p1, 0);
  188.     if ((int) p1 == FALSE)    {
  189.         if (wnd->CurrCol > wnd->wleft+ClientWidth(wnd)-1)
  190.             wnd->CurrCol = wnd->wleft+ClientWidth(wnd)-1;
  191.     }
  192.     else if (wnd->CurrCol < wnd->wleft)
  193.         wnd->CurrCol = wnd->wleft;
  194.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  195.     return rtn;
  196. }
  197. /* ----- Extend the marked block to the new x,y position ---- */
  198. static void ExtendBlock(WINDOW wnd, int x, int y)
  199. {
  200.     int bbl, bel;
  201.     int ptop = min(wnd->BlkBegLine, wnd->BlkEndLine);
  202.     int pbot = max(wnd->BlkBegLine, wnd->BlkEndLine);
  203.     char *lp = TextLine(wnd, wnd->wtop+y);
  204.     int len = (int) (strchr(lp, '\n') - lp);
  205.     x = min(x, len-wnd->wleft);
  206.     wnd->BlkEndCol = x+wnd->wleft;
  207.     wnd->BlkEndLine = y+wnd->wtop;
  208.     bbl = min(wnd->BlkBegLine, wnd->BlkEndLine);
  209.     bel = max(wnd->BlkBegLine, wnd->BlkEndLine);
  210.     while (ptop < bbl)    {
  211.         WriteTextLine(wnd, NULL, ptop, FALSE);
  212.         ptop++;
  213.     }
  214.     for (y = bbl; y <= bel; y++)
  215.         WriteTextLine(wnd, NULL, y, FALSE);
  216.     while (pbot > bel)    {
  217.         WriteTextLine(wnd, NULL, pbot, FALSE);
  218.         --pbot;
  219.     }
  220. }
  221. /* ----------- LEFT_BUTTON Message ---------- */
  222. static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  223. {
  224.     int MouseX = (int) p1 - GetClientLeft(wnd);
  225.     int MouseY = (int) p2 - GetClientTop(wnd);
  226.     RECT rc = ClientRect(wnd);
  227.     char *lp;
  228.     int len;
  229.     if (KeyBoardMarking)
  230.         return TRUE;
  231.     if (WindowMoving || WindowSizing)
  232.         return FALSE;
  233.     if (isMultiLine(wnd))    {
  234.         if (TextMarking)    {
  235.             if (!InsideRect(p1, p2, rc))    {
  236.                 if ((int)p1 == GetLeft(wnd))
  237.                     if (SendMessage(wnd, HORIZSCROLL, 0, 0))
  238.                         ExtendBlock(wnd, MouseX-1, MouseY);
  239.                 if ((int)p1 == GetRight(wnd))
  240.                     if (SendMessage(wnd, HORIZSCROLL, TRUE, 0))
  241.                         ExtendBlock(wnd, MouseX+1, MouseY);
  242.                 if ((int)p2 == GetTop(wnd))
  243.                     if (SendMessage(wnd, SCROLL, FALSE, 0))
  244.                         ExtendBlock(wnd, MouseX, MouseY+1);
  245.                 if ((int)p2 == GetBottom(wnd))
  246.                     if (SendMessage(wnd, SCROLL, TRUE, 0))
  247.                         ExtendBlock(wnd, MouseX, MouseY-1);
  248.                 SendMessage(wnd, PAINT, 0, 0);
  249.             }
  250.             return TRUE;
  251.         }
  252.         if (!InsideRect(p1, p2, rc))
  253.             return FALSE;
  254.         if (TextBlockMarked(wnd))    {
  255.             ClearTextBlock(wnd);
  256.             SendMessage(wnd, PAINT, 0, 0);
  257.         }
  258.         if (wnd->wlines)    {
  259.             if (MouseY > wnd->wlines-1)
  260.                 return TRUE;
  261.             lp = TextLine(wnd, MouseY+wnd->wtop);
  262.             len = (int) (strchr(lp, '\n') - lp);
  263.             MouseX = min(MouseX, len);
  264.             if (MouseX < wnd->wleft)    {
  265.                 MouseX = 0;
  266.                 SendMessage(wnd, KEYBOARD, HOME, 0);
  267.             }
  268.             ButtonDown = TRUE;
  269.             ButtonX = MouseX;
  270.             ButtonY = MouseY;
  271.         }
  272.         else
  273.             MouseX = MouseY = 0;
  274.         wnd->WndRow = MouseY;
  275.         SetLinePointer(wnd, MouseY+wnd->wtop);
  276.     }
  277.     if (isMultiLine(wnd) ||
  278.         (!TextBlockMarked(wnd)
  279.             && MouseX+wnd->wleft < strlen(wnd->text)))
  280.         wnd->CurrCol = MouseX+wnd->wleft;
  281.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  282.     return TRUE;
  283. }
  284. /* ----------- MOUSE_MOVED Message ---------- */
  285. static int MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  286. {
  287.     int MouseX = (int) p1 - GetClientLeft(wnd);
  288.     int MouseY = (int) p2 - GetClientTop(wnd);
  289.     RECT rc = ClientRect(wnd);
  290.     if (!InsideRect(p1, p2, rc))
  291.         return FALSE;
  292.     if (MouseY > wnd->wlines-1)
  293.         return FALSE;
  294.     if (ButtonDown)    {
  295.         SetAnchor(wnd, ButtonX+wnd->wleft, ButtonY+wnd->wtop);
  296.         TextMarking = TRUE;
  297.         rc = WindowRect(wnd);
  298.         SendMessage(NULL,MOUSE_TRAVEL,(PARAM) &rc, 0);
  299.         ButtonDown = FALSE;
  300.     }
  301.     if (TextMarking && !(WindowMoving || WindowSizing))    {
  302.         ExtendBlock(wnd, MouseX, MouseY);
  303.         return TRUE;
  304.     }
  305.     return FALSE;
  306. }
  307. static void StopMarking(WINDOW wnd)
  308. {
  309.     TextMarking = FALSE;
  310.     if (wnd->BlkBegLine > wnd->BlkEndLine)    {
  311.         swap(wnd->BlkBegLine, wnd->BlkEndLine);
  312.         swap(wnd->BlkBegCol, wnd->BlkEndCol);
  313.     }
  314.     if (wnd->BlkBegLine == wnd->BlkEndLine &&
  315.             wnd->BlkBegCol > wnd->BlkEndCol)
  316.         swap(wnd->BlkBegCol, wnd->BlkEndCol);
  317. }
  318. /* ----------- BUTTON_RELEASED Message ---------- */
  319. static int ButtonReleasedMsg(WINDOW wnd)
  320. {
  321.     if (isMultiLine(wnd))    {
  322.         ButtonDown = FALSE;
  323.         if (TextMarking && !(WindowMoving || WindowSizing))  {
  324.             /* release the mouse ouside the edit box */
  325.             SendMessage(NULL, MOUSE_TRAVEL, 0, 0);
  326.             StopMarking(wnd);
  327.             return TRUE;
  328.         }
  329.         else
  330.             PrevY = -1;
  331.     }
  332.     return FALSE;
  333. }
  334. /* ---- Process text block keys for multiline text box ---- */
  335. static void DoMultiLines(WINDOW wnd, int c, PARAM p2)
  336. {
  337.     if (isMultiLine(wnd))    {
  338.         if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))    {
  339.             int kx, ky;
  340.             SendMessage(NULL, CURRENT_KEYBOARD_CURSOR,
  341.                 (PARAM) &kx, (PARAM) &ky);
  342.             kx -= GetClientLeft(wnd);
  343.             ky -= GetClientTop(wnd);
  344.             switch (c)    {
  345.                 case HOME:
  346.                 case END:
  347.                 case CTRL_HOME:
  348.                 case CTRL_END:
  349.                 case PGUP:
  350.                 case PGDN:
  351.                 case CTRL_PGUP:
  352.                 case CTRL_PGDN:
  353.                 case UP:
  354.                 case DN:
  355.                 case FWD:
  356.                 case BS:
  357.                 case CTRL_FWD:
  358.                 case CTRL_BS:
  359.                     if (!KeyBoardMarking)    {
  360.                         if (TextBlockMarked(wnd))    {
  361.                             ClearTextBlock(wnd);
  362.                             SendMessage(wnd, PAINT, 0, 0);
  363.                         }
  364.                         KeyBoardMarking = TextMarking = TRUE;
  365.                         SetAnchor(wnd, kx+wnd->wleft,
  366.                                                 ky+wnd->wtop);
  367.                     }
  368.                     break;
  369.                 default:
  370.                     break;
  371.             }
  372.         }
  373.     }
  374. }
  375. /* ---------- page/scroll keys ----------- */
  376. static int DoScrolling(WINDOW wnd, int c, PARAM p2)
  377. {
  378.     switch (c)    {
  379.         case PGUP:
  380.         case PGDN:
  381.             if (isMultiLine(wnd))
  382.                 BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
  383.             break;
  384.         case CTRL_PGUP:
  385.         case CTRL_PGDN:
  386.             BaseWndProc(EDITBOX, wnd, KEYBOARD, c, p2);
  387.             break;
  388.         case HOME:
  389.             Home(wnd);
  390.             break;
  391.         case END:
  392.             End(wnd);
  393.             break;
  394.         case CTRL_FWD:
  395.             NextWord(wnd);
  396.             break;
  397.         case CTRL_BS:
  398.             PrevWord(wnd);
  399.             break;
  400.         case CTRL_HOME:
  401.             if (isMultiLine(wnd))    {
  402.                 SendMessage(wnd, SCROLLDOC, TRUE, 0);
  403.                 wnd->CurrLine = 0;
  404.                 wnd->WndRow = 0;
  405.             }
  406.             Home(wnd);
  407.             break;
  408.         case CTRL_END:
  409.             if (isMultiLine(wnd) &&
  410.                     wnd->WndRow+wnd->wtop+1 < wnd->wlines
  411.                         && wnd->wlines > 0) {
  412.                 SendMessage(wnd, SCROLLDOC, FALSE, 0);
  413.                 SetLinePointer(wnd, wnd->wlines-1);
  414.                 wnd->WndRow =
  415.                     min(ClientHeight(wnd)-1, wnd->wlines-1);
  416.                 Home(wnd);
  417.             }
  418.             End(wnd);
  419.             break;
  420.         case UP:
  421.             if (isMultiLine(wnd))
  422.                 Upward(wnd);
  423.             break;
  424.         case DN:
  425.             if (isMultiLine(wnd))
  426.                 Downward(wnd);
  427.             break;
  428.         case FWD:
  429.             Forward(wnd);
  430.             break;
  431.         case BS:
  432.             Backward(wnd);
  433.             break;
  434.         default:
  435.             return FALSE;
  436.     }
  437.     if (!KeyBoardMarking && TextBlockMarked(wnd))    {
  438.         ClearTextBlock(wnd);
  439.         SendMessage(wnd, PAINT, 0, 0);
  440.     }
  441.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  442.     return TRUE;
  443. }
  444. /* -------------- Del key ---------------- */
  445. static int DelKey(WINDOW wnd)
  446. {
  447.     char *currchar = CurrChar;
  448.     int repaint = *currchar == '\n';
  449.     if (TextBlockMarked(wnd))    {
  450.         SendMessage(wnd, COMMAND, ID_DELETETEXT, 0);
  451.         SendMessage(wnd, PAINT, 0, 0);
  452.         return TRUE;
  453.     }
  454.     if (*(currchar+1) == '\0')
  455.         return TRUE;
  456.     strcpy(currchar, currchar+1);
  457.     if (repaint)    {
  458.         BuildTextPointers(wnd);
  459.         SendMessage(wnd, PAINT, 0, 0);
  460.     }
  461.     else    {
  462.         ModTextPointers(wnd, wnd->CurrLine+1, -1);
  463.         WriteTextLine(wnd, NULL, wnd->WndRow+wnd->wtop, FALSE);
  464.     }
  465.     wnd->TextChanged = TRUE;
  466.     return FALSE;
  467. }
  468. /* ------------ Tab key ------------ */
  469. static int TabKey(WINDOW wnd, PARAM p2)
  470. {
  471.     if (isMultiLine(wnd))    {
  472.         int insmd = wnd->InsertMode;
  473.         do  {
  474.             char *cc = CurrChar+1;
  475.             if (!insmd && *cc == '\0')
  476.                 break;
  477.             if (wnd->textlen == wnd->MaxTextLength)
  478.                 break;
  479.             SendMessage(wnd,KEYBOARD,insmd ? ' ' : FWD,0);
  480.         } while (wnd->CurrCol % cfg.Tabs);
  481.         return TRUE;
  482.     }
  483.     PostMessage(GetParent(wnd), KEYBOARD, '\t', p2);
  484.     return FALSE;
  485. }
  486. /* ------------ Shift+Tab key ------------ */
  487. static int ShiftTabKey(WINDOW wnd, PARAM p2)
  488. {
  489.     if (isMultiLine(wnd))    {
  490.         do  {
  491.             if (CurrChar == GetText(wnd))
  492.                 break;
  493.             SendMessage(wnd,KEYBOARD,BS,0);
  494.         } while (wnd->CurrCol % cfg.Tabs);
  495.         return TRUE;
  496.     }
  497.     PostMessage(GetParent(wnd), KEYBOARD, SHIFT_HT, p2);
  498.     return FALSE;
  499. }
  500. /* --------- All displayable typed keys ------------- */
  501. static void KeyTyped(WINDOW wnd, int c)
  502. {
  503.     char *currchar = CurrChar;
  504.     if ((c != '\n' && c < ' ') || (c & 0x1000))
  505.         /* ---- not recognized by editor --- */
  506.         return;
  507.     if (!isMultiLine(wnd) && TextBlockMarked(wnd))    {
  508.         ResetEditBox(wnd);
  509.         currchar = CurrChar;
  510.     }
  511.     if (*currchar == '\0')    {
  512.         /* ---- typing at end of text ---- */
  513.         if (currchar == wnd->text+wnd->MaxTextLength)    {
  514.             /* ---- typing at the end of maximum buffer ---- */
  515.             beep();
  516.             return;
  517.         }
  518.         /* --- insert a newline at end of text --- */
  519.         *currchar = '\n';
  520.         *(currchar+1) = '\0';
  521.         BuildTextPointers(wnd);
  522.     }
  523.     /* --- displayable char or newline --- */
  524.     if (c == '\n' || wnd->InsertMode || *currchar == '\n') {
  525.         /* ------ inserting the keyed character ------ */
  526.         if (wnd->text[wnd->textlen-1] != '\0')    {
  527.             /* --- the current text buffer is full --- */
  528.             if (wnd->textlen == wnd->MaxTextLength)    {
  529.                 /* --- text buffer is at maximum size --- */
  530.                 beep();
  531.                 return;
  532.             }
  533.             /* ---- increase the text buffer size ---- */
  534.             wnd->textlen += GROWLENGTH;
  535.             /* --- but not above maximum size --- */
  536.             if (wnd->textlen > wnd->MaxTextLength)
  537.                 wnd->textlen = wnd->MaxTextLength;
  538.             wnd->text = realloc(wnd->text, wnd->textlen+2);
  539.             wnd->text[wnd->textlen-1] = '\0';
  540.             currchar = CurrChar;
  541.         }
  542.         memmove(currchar+1, currchar, strlen(currchar)+1);
  543.         ModTextPointers(wnd, wnd->CurrLine+1, 1);
  544.         if (isMultiLine(wnd) && wnd->wlines > 1)
  545.             wnd->textwidth = max(wnd->textwidth,
  546.                 (int) (TextLine(wnd, wnd->CurrLine+1)-
  547.                 TextLine(wnd, wnd->CurrLine)));
  548.         else
  549.             wnd->textwidth = max(wnd->textwidth,
  550.                 strlen(wnd->text));
  551.         WriteTextLine(wnd, NULL,
  552.             wnd->wtop+wnd->WndRow, FALSE);
  553.     }
  554.     /* ----- put the char in the buffer ----- */
  555.     *currchar = c;
  556.     wnd->TextChanged = TRUE;
  557.     if (c == '\n')    {
  558.         wnd->wleft = 0;
  559.         BuildTextPointers(wnd);
  560.         End(wnd);
  561.         Forward(wnd);
  562.         SendMessage(wnd, PAINT, 0, 0);
  563.         return;
  564.     }
  565.     /* ---------- test end of window --------- */
  566.     if (WndCol == ClientWidth(wnd)-1)    {
  567.         int dif;
  568.         char *cp = currchar;
  569.         while (*cp != ' ' && cp != TextLine(wnd, wnd->CurrLine))
  570.             --cp;
  571.         if (!isMultiLine(wnd) ||
  572.             cp == TextLine(wnd, wnd->CurrLine) ||
  573.                 !wnd->WordWrapMode)
  574.             SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  575.         else    {
  576.             dif = 0;
  577.             if (c != ' ')    {
  578.                 dif = (int) (currchar - cp);
  579.                 wnd->CurrCol -= dif;
  580.                 SendMessage(wnd, KEYBOARD, DEL, 0);
  581.                 --dif;
  582.             }
  583.             SendMessage(wnd, KEYBOARD, '\r', 0);
  584.             currchar = CurrChar;
  585.             wnd->CurrCol = dif;
  586.             if (c == ' ')
  587.                 return;
  588.         }
  589.     }
  590.     /* ------ display the character ------ */
  591.     SetStandardColor(wnd);
  592.     PutWindowChar(wnd, c, WndCol, wnd->WndRow);
  593.     /* ----- advance the pointers ------ */
  594.     wnd->CurrCol++;
  595. }
  596. /* ------------ screen changing key strokes ------------- */
  597. static int DoKeyStroke(WINDOW wnd, int c, PARAM p2)
  598. {
  599.     switch (c)    {
  600.         case RUBOUT:
  601.             Backward(wnd);
  602.         case DEL:
  603.             if (DelKey(wnd))
  604.                 return TRUE;
  605.             break;
  606.         case SHIFT_HT:
  607.             if (ShiftTabKey(wnd, p2))
  608.                 return TRUE;
  609.             break;
  610.         case '\t':
  611.             if (TabKey(wnd, p2))
  612.                 return TRUE;
  613.             break;
  614.         case '\r':
  615.             if (!isMultiLine(wnd))    {
  616.                 PostMessage(GetParent(wnd), KEYBOARD, c, p2);
  617.                 break;
  618.             }
  619.             c = '\n';
  620.         default:
  621.             if (TextBlockMarked(wnd))    {
  622.                 SendMessage(wnd, COMMAND, ID_DELETETEXT, 0);
  623.                 SendMessage(wnd, PAINT, 0, 0);
  624.             }
  625.             KeyTyped(wnd, c);
  626.             break;
  627.     }
  628.     return FALSE;
  629. }
  630. /* ----------- KEYBOARD Message ---------- */
  631. static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  632. {
  633.     int c = (int) p1;
  634.     if (WindowMoving || WindowSizing || ((int)p2 & ALTKEY))
  635.         return FALSE;
  636.     switch (c)    {
  637.         /* --- these keys get processed by lower classes --- */
  638.         case ESC:
  639.         case F1:
  640.         case F2:
  641.         case F3:
  642.         case F4:
  643.         case F5:
  644.         case F6:
  645.         case F7:
  646.         case F8:
  647.         case F9:
  648.         case F10:
  649.         case INS:
  650.         case SHIFT_INS:
  651.         case SHIFT_DEL:
  652.             return FALSE;
  653.         /* --- these keys get processed here --- */
  654.         case CTRL_FWD:
  655.         case CTRL_BS:
  656.         case CTRL_HOME:
  657.         case CTRL_END:
  658.         case CTRL_PGUP:
  659.         case CTRL_PGDN:
  660.             break;
  661.         default:
  662.             /* other ctrl keys get processed by lower classes */
  663.             if ((int)p2 & CTRLKEY)
  664.                 return FALSE;
  665.             /* --- all other keys get processed here --- */
  666.             break;
  667.     }
  668.     DoMultiLines(wnd, c, p2);
  669.     if (DoScrolling(wnd, c, p2))    {
  670.         if (KeyBoardMarking)
  671.             ExtendBlock(wnd, WndCol, wnd->WndRow);
  672.     }
  673.     else if (!TestAttribute(wnd, READONLY))    {
  674.         DoKeyStroke(wnd, c, p2);
  675.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  676.     }
  677.     return TRUE;
  678. }
  679. /* ----------- SHIFT_CHANGED Message ---------- */
  680. static void ShiftChangedMsg(WINDOW wnd, PARAM p1)
  681. {
  682.     if (!((int)p1 & (LEFTSHIFT | RIGHTSHIFT)) &&
  683.                                    KeyBoardMarking)    {
  684.         StopMarking(wnd);
  685.         KeyBoardMarking = FALSE;
  686.     }
  687. }
  688. /* ----------- ID_DELETETEXT Command ---------- */
  689. static void DeleteTextCmd(WINDOW wnd)
  690. {
  691.     if (TextBlockMarked(wnd))    {
  692.         char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
  693.         char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
  694.         int len = (int) (bel - bbl);
  695.         SaveDeletedText(wnd, bbl, len);
  696.         wnd->TextChanged = TRUE;
  697.         strcpy(bbl, bel);
  698.         wnd->CurrLine = TextLineNumber(wnd, bbl-wnd->BlkBegCol);
  699.         wnd->CurrCol = wnd->BlkBegCol;
  700.         wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  701.         if (wnd->WndRow < 0)    {
  702.             wnd->wtop = wnd->BlkBegLine;
  703.             wnd->WndRow = 0;
  704.         }
  705.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  706.         ClearTextBlock(wnd);
  707.         BuildTextPointers(wnd);
  708.     }
  709. }
  710. /* ----------- ID_CLEAR Command ---------- */
  711. static void ClearCmd(WINDOW wnd)
  712. {
  713.     if (TextBlockMarked(wnd))    {
  714.         char *bbl=TextLine(wnd,wnd->BlkBegLine)+wnd->BlkBegCol;
  715.         char *bel=TextLine(wnd,wnd->BlkEndLine)+wnd->BlkEndCol;
  716.         int len = (int) (bel - bbl);
  717.         SaveDeletedText(wnd, bbl, len);
  718.         wnd->CurrLine = TextLineNumber(wnd, bbl);
  719.         wnd->CurrCol = wnd->BlkBegCol;
  720.         wnd->WndRow = wnd->BlkBegLine - wnd->wtop;
  721.         if (wnd->WndRow < 0)    {
  722.             wnd->WndRow = 0;
  723.             wnd->wtop = wnd->BlkBegLine;
  724.         }
  725.         /* ------ change all text lines in block to \n ----- */
  726.         while (bbl < bel)    {
  727.             char *cp = strchr(bbl, '\n');
  728.             if (cp > bel)
  729.                 cp = bel;
  730.             strcpy(bbl, cp);
  731.             bel -= (int) (cp - bbl);
  732.             bbl++;
  733.         }
  734.         ClearTextBlock(wnd);
  735.         BuildTextPointers(wnd);
  736.         SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  737.         SendMessage(wnd, PAINT, 0, 0);
  738.         wnd->TextChanged = TRUE;
  739.     }
  740. }
  741. /* ----------- ID_UNDO Command ---------- */
  742. static void UndoCmd(WINDOW wnd)
  743. {
  744.     if (wnd->DeletedText != NULL)    {
  745.         PasteText(wnd, wnd->DeletedText, wnd->DeletedLength);
  746.         free(wnd->DeletedText);
  747.         wnd->DeletedText = NULL;
  748.         wnd->DeletedLength = 0;
  749.         SendMessage(wnd, PAINT, 0, 0);
  750.     }
  751. }
  752. /* ----------- ID_PARAGRAPH Command ---------- */
  753. static void ParagraphCmd(WINDOW wnd)
  754. {
  755.     int bc, ec, fl, el, Blocked;
  756.     char *bl, *bbl, *bel, *bb;
  757.  
  758.     el = wnd->BlkEndLine;
  759.     ec = wnd->BlkEndCol;
  760.     if (!TextBlockMarked(wnd))    {
  761.         Blocked = FALSE;
  762.         /* ---- forming paragraph from cursor position --- */
  763.         fl = wnd->wtop + wnd->WndRow;
  764.         bbl = bel = bl = TextLine(wnd, wnd->CurrLine);
  765.         if ((bc = wnd->CurrCol) >= ClientWidth(wnd))
  766.             bc = 0;
  767.         Home(wnd);
  768.         /* ---- locate the end of the paragraph ---- */
  769.         while (*bel)    {
  770.             int blank = TRUE;
  771.             char *bll = bel;
  772.             /* --- blank line marks end of paragraph --- */
  773.             while (*bel && *bel != '\n')    {
  774.                 if (*bel != ' ')
  775.                     blank = FALSE;
  776.                 bel++;
  777.             }
  778.             if (blank)    {
  779.                 bel = bll;
  780.                 break;
  781.             }
  782.             if (*bel)
  783.                 bel++;
  784.         }
  785.         if (bel == bbl)    {
  786.             SendMessage(wnd, KEYBOARD, DN, 0);
  787.             return;
  788.         }
  789.         if (*bel == '\0')
  790.             --bel;
  791.         if (*bel == '\n')
  792.             --bel;
  793.     }
  794.     else    {
  795.         /* ---- forming paragraph from marked block --- */
  796.         Blocked = TRUE;
  797.         bbl = TextLine(wnd, wnd->BlkBegLine) + wnd->BlkBegCol;
  798.         bel = TextLine(wnd, wnd->BlkEndLine) + wnd->BlkEndCol;
  799.         fl = wnd->BlkBegLine;
  800.         bc = wnd->CurrCol = wnd->BlkBegCol;
  801.         wnd->CurrLine = fl;
  802.         if (fl < wnd->wtop)
  803.             wnd->wtop = fl;
  804.         wnd->WndRow = fl - wnd->wtop;
  805.         SendMessage(wnd, KEYBOARD, '\r', 0);
  806.         el++, fl++;
  807.         if (bc != 0)    {
  808.             SendMessage(wnd, KEYBOARD, '\r', 0);
  809.             el++, fl ++;
  810.         }
  811.         bc = 0;
  812.         bl = TextLine(wnd, fl);
  813.         wnd->CurrLine = fl;
  814.         bbl = bl + bc;
  815.         bel = TextLine(wnd, el) + ec;
  816.     }
  817.     /* --- change all newlines in block to spaces --- */
  818.     while (CurrChar < bel)    {
  819.         if (*CurrChar == '\n')    {
  820.             *CurrChar = ' ';
  821.             wnd->CurrLine++;
  822.             wnd->CurrCol = 0;
  823.         }
  824.         else
  825.             wnd->CurrCol++;
  826.     }
  827.     /* ---- insert newlines at new margin boundaries ---- */
  828.     bb = bbl;
  829.     while (bbl < bel)    {
  830.         bbl++;
  831.         if ((int)(bbl - bb) == ClientWidth(wnd)-1)    {
  832.             while (*bbl != ' ' && bbl > bb)
  833.                 --bbl;
  834.             if (*bbl != ' ')    {
  835.                 bbl = strchr(bbl, ' ');
  836.                 if (bbl == NULL || bbl >= bel)
  837.                     break;
  838.             }
  839.             *bbl = '\n';
  840.             bb = bbl+1;
  841.         }
  842.     }
  843.     ec = (int)(bel - bb);
  844.     BuildTextPointers(wnd);
  845.     if (Blocked)    {
  846.         /* ---- position cursor at end of new paragraph ---- */
  847.         if (el < wnd->wtop ||
  848.                 wnd->wtop + ClientHeight(wnd) < el)
  849.             wnd->wtop = el-ClientHeight(wnd);
  850.         if (wnd->wtop < 0)
  851.             wnd->wtop = 0;
  852.         wnd->WndRow = el - wnd->wtop;
  853.         wnd->CurrLine = el;
  854.         wnd->CurrCol = ec;
  855.         SendMessage(wnd, KEYBOARD, '\r', 0);
  856.         SendMessage(wnd, KEYBOARD, '\r', 0);
  857.     }
  858.     else    {
  859.         /* --- put cursor back at beginning --- */
  860.         wnd->CurrLine = TextLineNumber(wnd, bl);
  861.         wnd->CurrCol = bc;
  862.         if (fl < wnd->wtop)
  863.             wnd->wtop = fl;
  864.         wnd->WndRow = fl - wnd->wtop;
  865.     }
  866.     SendMessage(wnd, PAINT, 0, 0);
  867.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  868.     wnd->TextChanged = TRUE;
  869.     BuildTextPointers(wnd);
  870. }
  871. /* ----------- COMMAND Message ---------- */
  872. static int CommandMsg(WINDOW wnd, PARAM p1)
  873. {
  874.     switch ((int)p1)    {
  875.         case ID_DELETETEXT:
  876.             DeleteTextCmd(wnd);
  877.             return TRUE;
  878.         case ID_CLEAR:
  879.             ClearCmd(wnd);
  880.             return TRUE;
  881.         case ID_UNDO:
  882.             UndoCmd(wnd);
  883.             return TRUE;
  884.         case ID_PARAGRAPH:
  885.             ParagraphCmd(wnd);
  886.             return TRUE;
  887.         default:
  888.             break;
  889.     }
  890.     return FALSE;
  891. }
  892. /* ---------- CLOSE_WINDOW Message ----------- */
  893. static void CloseWindowMsg(WINDOW wnd)
  894. {
  895.     SendMessage(NULL, HIDE_CURSOR, 0, 0);
  896.     if (wnd->DeletedText != NULL)
  897.         free(wnd->DeletedText);
  898. }
  899. /* ------- Window processing module for EDITBOX class ------ */
  900. int EditBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  901. {
  902.     int rtn;
  903.     switch (msg)    {
  904.         case CREATE_WINDOW:
  905.             return CreateWindowMsg(wnd);
  906.         case ADDTEXT:
  907.             return AddTextMsg(wnd, p1, p2);
  908.         case SETTEXT:
  909.             return SetTextMsg(wnd, p1);
  910.         case CLEARTEXT:
  911.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  912.             ResetEditBox(wnd);
  913.             return rtn;
  914.         case GETTEXT:
  915.             return GetTextMsg(wnd, p1, p2);
  916.         case SETTEXTLENGTH:
  917.             return SetTextLengthMsg(wnd, (unsigned) p1);
  918.         case KEYBOARD_CURSOR:
  919.             return KeyboardCursorMsg(wnd, p1, p2);
  920.         case SETFOCUS:
  921.         case PAINT:
  922.         case MOVE:
  923.             rtn = BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  924.             SendMessage(wnd,KEYBOARD_CURSOR,WndCol,wnd->WndRow);
  925.             return rtn;
  926.         case SIZE:
  927.             return SizeMsg(wnd, p1, p2);
  928.         case SCROLL:
  929.             return ScrollMsg(wnd, p1);
  930.         case HORIZSCROLL:
  931.             return HorizScrollMsg(wnd, p1);
  932.         case SCROLLPAGE:
  933.             return ScrollPageMsg(wnd, p1);
  934.         case HORIZPAGE:
  935.             return HorizPageMsg(wnd, p1);
  936.         case LEFT_BUTTON:
  937.             if (LeftButtonMsg(wnd, p1, p2))
  938.                 return TRUE;
  939.             break;
  940.         case MOUSE_MOVED:
  941.             if (MouseMovedMsg(wnd, p1, p2))
  942.                 return TRUE;
  943.             break;
  944.         case BUTTON_RELEASED:
  945.             if (ButtonReleasedMsg(wnd))
  946.                 return TRUE;
  947.             break;
  948.         case KEYBOARD:
  949.             if (KeyboardMsg(wnd, p1, p2))
  950.                 return TRUE;
  951.             break;
  952.         case SHIFT_CHANGED:
  953.             ShiftChangedMsg(wnd, p1);
  954.             break;
  955.         case COMMAND:
  956.             if (CommandMsg(wnd, p1))
  957.                 return TRUE;
  958.             break;
  959.         case CLOSE_WINDOW:
  960.             CloseWindowMsg(wnd);
  961.             break;
  962.         default:
  963.             break;
  964.     }
  965.     return BaseWndProc(EDITBOX, wnd, msg, p1, p2);
  966. }
  967. /* ------ save deleted text for the Undo command ------ */
  968. static void SaveDeletedText(WINDOW wnd, char *bbl, int len)
  969. {
  970.     wnd->DeletedLength = len;
  971.     if ((wnd->DeletedText=realloc(wnd->DeletedText,len))!=NULL)
  972.         memmove(wnd->DeletedText, bbl, len);
  973. }
  974. /* ---- cursor right key: right one character position ---- */
  975. static void Forward(WINDOW wnd)
  976. {
  977.     char *cc = CurrChar+1;
  978.     if (*cc == '\0')
  979.         return;
  980.     if (*CurrChar == '\n')    {
  981.         Home(wnd);
  982.         Downward(wnd);
  983.     }
  984.     else    {
  985.         wnd->CurrCol++;
  986.         if (WndCol == ClientWidth(wnd))
  987.             SendMessage(wnd, HORIZSCROLL, TRUE, 0);
  988.     }
  989. }
  990. /* ----- stick the moving cursor to the end of the line ---- */
  991. static void StickEnd(WINDOW wnd)
  992. {
  993.     char *cp = TextLine(wnd, wnd->CurrLine);
  994.     char *cp1 = strchr(cp, '\n');
  995.     int len = cp1 ? (int) (cp1 - cp) : 0;
  996.     wnd->CurrCol = min(len, wnd->CurrCol);
  997.     if (wnd->wleft > wnd->CurrCol)    {
  998.         wnd->wleft = max(0, wnd->CurrCol - 4);
  999.         SendMessage(wnd, PAINT, 0, 0);
  1000.     }
  1001.     else if (wnd->CurrCol-wnd->wleft >= ClientWidth(wnd))    {
  1002.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  1003.         SendMessage(wnd, PAINT, 0, 0);
  1004.     }
  1005. }
  1006. /* --------- cursor down key: down one line --------- */
  1007. static void Downward(WINDOW wnd)
  1008. {
  1009.     if (isMultiLine(wnd) &&
  1010.             wnd->WndRow+wnd->wtop+1 < wnd->wlines)  {
  1011.         wnd->CurrLine++;
  1012.         if (wnd->WndRow == ClientHeight(wnd)-1)
  1013.             SendMessage(wnd, SCROLL, TRUE, 0);
  1014.         wnd->WndRow++;
  1015.         StickEnd(wnd);
  1016.     }
  1017. }
  1018. /* -------- cursor up key: up one line ------------ */
  1019. static void Upward(WINDOW wnd)
  1020. {
  1021.     if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1022.         if (wnd->CurrLine > 0)
  1023.             --wnd->CurrLine;
  1024.         if (wnd->WndRow == 0)
  1025.             SendMessage(wnd, SCROLL, FALSE, 0);
  1026.         --wnd->WndRow;
  1027.         StickEnd(wnd);
  1028.     }
  1029. }
  1030. /* ---- cursor left key: left one character position ---- */
  1031. static void Backward(WINDOW wnd)
  1032. {
  1033.     if (wnd->CurrCol)    {
  1034.         if (wnd->CurrCol-- <= wnd->wleft)
  1035.             if (wnd->wleft != 0)
  1036.                 SendMessage(wnd, HORIZSCROLL, FALSE, 0);
  1037.     }
  1038.     else if (isMultiLine(wnd) && wnd->CurrLine != 0)    {
  1039.         Upward(wnd);
  1040.         End(wnd);
  1041.     }
  1042. }
  1043. /* -------- End key: to end of line ------- */
  1044. static void End(WINDOW wnd)
  1045. {
  1046.     while (*CurrChar && *CurrChar != '\n')
  1047.         ++wnd->CurrCol;
  1048.     if (WndCol >= ClientWidth(wnd))    {
  1049.         wnd->wleft = wnd->CurrCol - (ClientWidth(wnd)-1);
  1050.         SendMessage(wnd, PAINT, 0, 0);
  1051.     }
  1052. }
  1053. /* -------- Home key: to beginning of line ------- */
  1054. static void Home(WINDOW wnd)
  1055. {
  1056.     wnd->CurrCol = 0;
  1057.     if (wnd->wleft != 0)    {
  1058.         wnd->wleft = 0;
  1059.         SendMessage(wnd, PAINT, 0, 0);
  1060.     }
  1061. }
  1062. /* -- Ctrl+cursor right key: to beginning of next word -- */
  1063. static void NextWord(WINDOW wnd)
  1064. {
  1065.     int savetop = wnd->wtop;
  1066.     int saveleft = wnd->wleft;
  1067.     ClearVisible(wnd);
  1068.     while (!isWhite(*CurrChar))    {
  1069.         char *cc = CurrChar+1;
  1070.         if (*cc == '\0')
  1071.             break;
  1072.         Forward(wnd);
  1073.     }
  1074.     while (isWhite(*CurrChar))    {
  1075.         char *cc = CurrChar+1;
  1076.         if (*cc == '\0')
  1077.             break;
  1078.         Forward(wnd);
  1079.     }
  1080.     SetVisible(wnd);
  1081.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1082.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1083.         SendMessage(wnd, PAINT, 0, 0);
  1084. }
  1085. /* -- Ctrl+cursor left key: to beginning of previous word -- */
  1086. static void PrevWord(WINDOW wnd)
  1087. {
  1088.     int savetop = wnd->wtop;
  1089.     int saveleft = wnd->wleft;
  1090.     ClearVisible(wnd);
  1091.     Backward(wnd);
  1092.     while (isWhite(*CurrChar))    {
  1093.         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  1094.             break;
  1095.         Backward(wnd);
  1096.     }
  1097.     while (!isWhite(*CurrChar))    {
  1098.         if (wnd->CurrLine == 0 && wnd->CurrCol == 0)
  1099.             break;
  1100.         Backward(wnd);
  1101.     }
  1102.     if (isWhite(*CurrChar))
  1103.         Forward(wnd);
  1104.     SetVisible(wnd);
  1105.     if (wnd->wleft != saveleft)
  1106.         if (wnd->CurrCol >= saveleft)
  1107.             if (wnd->CurrCol - saveleft < ClientWidth(wnd))
  1108.                 wnd->wleft = saveleft;
  1109.     SendMessage(wnd, KEYBOARD_CURSOR, WndCol, wnd->WndRow);
  1110.     if (wnd->wtop != savetop || wnd->wleft != saveleft)
  1111.         SendMessage(wnd, PAINT, 0, 0);
  1112. }
  1113. /* ----- reset the text attributes of an EDITBOX ------- */
  1114. void ResetEditBox(WINDOW wnd)
  1115. {
  1116.     unsigned blen = EditBufLen(wnd)+2;
  1117.     wnd->text = realloc(wnd->text, blen);
  1118.     memset(wnd->text, 0, blen);
  1119.     wnd->wlines = 0;
  1120.     wnd->CurrLine = 0;
  1121.     wnd->CurrCol = 0;
  1122.     wnd->WndRow = 0;
  1123.     wnd->wleft = 0;
  1124.     wnd->wtop = 0;
  1125.     wnd->textwidth = 0;
  1126.     wnd->TextChanged = FALSE;
  1127.     ClearTextPointers(wnd);
  1128.     ClearTextBlock(wnd);
  1129. }
  1130. /* ----- modify text pointers from a specified position
  1131.                 by a specified plus or minus amount ----- */
  1132. static void ModTextPointers(WINDOW wnd, int lineno, int var)
  1133. {
  1134.     while (lineno < wnd->wlines)
  1135.         *((wnd->TextPointers) + lineno++) += var;
  1136. }
  1137.  
  1138.